package com.smarthospital.common.util;

import com.squareup.okhttp.HttpUrl;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

/**
 * create by sym  2021/9/12 20:03.
 * 微信支付 签名工具
 * todo  懒加载  微信支付平台证书序列号更新机制
 */
public class WXSignUtil {


    public static String getToken(String method, HttpUrl url,String body) throws Exception {
        String nonceStr = IDGeneratorUtil.getOneceString();
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("utf-8"));

        return  "WECHATPAY2-SHA256-RSA2048 "+
                "mchid=\"" + "1612597675" + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + "50A058887420B8C1C2C32320585F8FA64FAF00C2" + "\","
                + "signature=\"" + signature + "\"";
    }

    static String sign(byte[] message) throws SignatureException, InvalidKeyException, NoSuchAlgorithmException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        PrivateKey privateKey = PemUtil.loadPrivateKey(WXSignUtil.class.getClassLoader().getResourceAsStream("apiclient_key.pem"));
        sign.initSign(privateKey);
        sign.update(message);

        return Base64.getEncoder().encodeToString(sign.sign());
    }

    static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }

        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }


    /**
     * 证书解密
     * @param apiV3Key
     * @param associatedData
     * @param nonce
     * @param ciphertext
     * @return
     * @throws Exception
     */
    public static String decryptResponseBody(String apiV3Key,String associatedData, String nonce, String ciphertext) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

            SecretKeySpec key = new SecretKeySpec(apiV3Key.getBytes(StandardCharsets.UTF_8), "AES");
            GCMParameterSpec spec = new GCMParameterSpec(128, nonce.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));

            byte[] bytes;
            try {
                bytes = cipher.doFinal(Base64Utils.decodeFromString(ciphertext));
            } catch (GeneralSecurityException e) {
                throw new IllegalArgumentException(e);
            }
            return new String(bytes, StandardCharsets.UTF_8);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(e);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static void main(String[] args)throws Exception {
        System.out.println(decryptResponseBody("6790594D95F2C4EBDE182A1BC4D2E7E7",
                "certificate",
                "71753ee94b4b",
                "PGQ1oyl5c6wFee1O9s/s21RvI06t3YiuGwac+hKT69jZ5B/cqSov4ZX6HuTLtFDq1LJAdP//R3qagNcNDm9pIAfDnQlXiykNN7KqbmglLKkdS5JWZFwsAeAEgjZ0HbU3JOicvCldEwEqQ3aSsKzsKCb6J9cWo7E6l+T7ZxTRFaOp3U7eS/n1Kq3oGmMjG3HQ0PwJD9dh7FIClzilTwVzy2W1WngYHMkwBf/mjJD8GPiyFv+tjpV+uw87UGz/hctP8YN1KEqWKGZLeSdX/MZ686a+pYG1o3RamaFET6Ah5TcOYjW5HCmQkbrIGo/QkG0AzFXIB9kREFw0WH6DiY7TN+HZSaSv2d9z1UtHAcgf8Z+16ufCco+1NdqEui1PTM/Qu3gp1dwTUs+wGjUXePUr1ndR0yxShHBSFpj8vwlR/shfbN7F3WXkMM0e+82dmApvVoMYKpFv7eSDQ2qVcjU4+lnnojR8DCuYzSaFnAAI/yKv/cLkpXeBQFE8GvBEuJCZv7HEyhBx00X+c5DLwVr27oxNQ8QK1AtV1Z0YGeaCglBm5jW3WDU/CLHMM9g9I62pTcUIZCdfSK8fR7yQvTK/O+ccD9vlw/5WoWWlncKueulLbbdaj3kW3T9666ah9Cgj8etXWQE7cxr+dFPWVKA36vQk39OoJMHYpMTTjHlqmRjt/NtVR+MBPl6/T5HFRYmKuvuF9KCiAG9t0tcEAwBrSN+RfKYL5DXwN8EAl8usKlX5ZT0Twdt3y77BpblTb+YKPBiBGpQJylMF7pCF4FzTRNT6TFM6mCv44uXJaVGrzJmlMUqD7igzdRNG6WAGdSKkplmEmnBiTdQ0Eejqs/J+xlIml/Xu6XwP2gu15hwXD9VgND78qRrZQQJHhTe2JL4CMFbHglAMvqHyniOYAgpkgFuYUUdXI3TaFxBEp2/j/QeXk7JYMAZOA3q3pxsUvGT75mxAgwO8URGwTNP0vGqMjr4/851cy2TiT0sHPzSmOiXEznRuwfbR5t2yO/1PzVUd91y7mLX4yunqjycInKm+IhNNNH8oBH9bQTl23JSVa5Lc+hV+ieoT/w7pWM7ObOA0uLOVaQxeSknMHjOsYR7oJKLqXX/HZjlzqTBUN06ZoGlN0WGVnD1HQTJlmvWpTKTEvJv6Ur4+AwcCCPVXne23Jpl4J3FZleHJNT1SzWj6ZTrE1pRMwiu3PtRmwlQGmY+AFvS2kXBb8m1laahrf9QhtsXj9MBqQ9KYPKTpxsSCqRrCPS4Avq/WipLRrazm8tb0/ROl9PsksMqpCtG5QxIKMaT/ciHV3nMNPB1JDRvmfOfYkU6FaJ6eLHteOjG11iybnfpDvOKkqJqo3lzsBvWRVTEKZxazkf4gU9jhplGMJnc2JKDGGgvCMSommmxAKq+wAnVZt1VXHfHlf7/XinYJyL1zmwOEzFzQK5MIIaR0lr4bgVqWiVg+NM4S5tAUTY+hCdFV6D6ebNKPO+lArJlVz9vIBB4EeHbeA6TZBbXzcYThsHqWllWQ9sLcCf8fMiuDeDRcUq9qMZBvT1DKqN/mwg00fs3yoDv4bD9tSTYWSOcf6gZ1C44l00uqt/Cv805MeDeRQB6erK93vO6FPcJxRcfTPvAxwH2CXvQ4RD/Cl2pALEbM4KM8i1Kjx/Fo7xgMwqhpmrS4zWe4y+g+lytEOeNDgiq3chkZQico7lML3XcSFifSfT3pSB5ydpcTU4UW6QjlIyaPYYldcqJBW/M/JgAKwCfnUhFbTWLi7rYLlvFV2FgR2eMTm7qcQG50e6X481dz6elKq75T9Z3XpalSgNNW9txyyfZPVGkzq35J+q+7zEmJnt7NYpK5iTbHJkHZI4vrogcwyZVRTIWNvlCcTWr4sI7nlA=="));
    }
}
